package org.flik.client.main;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.flik.client.main.service.UserServiceAsync;
import org.flik.client.shared.ClientUtils;
import org.flik.client.shared.CommonAsyncCallback;
import org.flik.server.dto.TextLongPair;
import org.flik.server.dto.TicketChange;
import org.flik.server.dto.TicketDetail;
import org.flik.server.dto.TicketDetailComment;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class TicketDetailPanel extends ResizeComposite {

	private static TicketDetailsUiBinder uiBinder = GWT.create(TicketDetailsUiBinder.class);

	interface TicketDetailsUiBinder extends UiBinder<Widget, TicketDetailPanel> {
	}
	@UiField
	Button saveButton; 
	
	@UiField
	HTML reportedBy, reportedDate, project, description;
	
	@UiField
	Label title;
	
	@UiField
	VerticalPanel comments;
	
	@UiField
	ListBox ticketType, status, assignedTo; 

	@UiField
	TextArea comment; 
	
	@UiField
	ScrollPanel scrollPanel;
	
	private TicketChange ticketChange;
	
	private void initTicketChange(){
		ticketChange = new TicketChange();
		ticketChange.setTicketId(ticketId);
	}
	@UiHandler("saveButton")
	void onSaveButtonClick(ClickEvent event){
		String commentText = comment.getValue().trim();
		if (!commentText.equals("")){
			ticketChange.setCommentText(commentText);
			addTicketCommentWidget(commentText);
			comment.setValue("");
		}
		saveScheduler.saveNow();
	}
	private void addTicketCommentWidget(String commentText){
		TicketDetailComments ticketDetail = new TicketDetailComments(
				new TicketDetailComment(null, commentText, new Date(),
				Main.getLoggedInUserFullName(), 					
				null));
		comments.add(ticketDetail);//TODO: Link database id back to this comment. 
		scrollPanel.scrollToBottom();
	}
	@Override
	public void onResize() {
		super.onResize();
	}
	@UiHandler("ticketType")
	void onTicketTypeChange(ChangeEvent event){
		ticketChange.setTicketTypeId(Long.parseLong(ticketType.getValue(ticketType.getSelectedIndex())));
	}
	
	private SaveScheduler saveScheduler = new SaveScheduler();

	private Long ticketId; 
	
	private class SaveScheduler extends Timer{

		private static final int TIMER_DELAY_MILLIS = 60/*seconds*/ * 1000;
		private boolean scheduled = true; 
		
		@Override
		public void run() {
			UserServiceAsync.INSTANCE.save(ticketChange, new CommonAsyncCallback<Void>() {

				@Override
				public void onSuccess(Void result) {
					ClientUtils.hideRemoteCommunicationMessage();
				}
			});
			saveButton.setEnabled(false);
			initTicketChange();
			scheduled = false; 
		}
		public void saveNow() {
			save(0);
		}
		public void save() {
			save(TIMER_DELAY_MILLIS);
		}
		@Override
		public void schedule(int delayMillis) {
			super.schedule(delayMillis);
			scheduled = true;
		}
		private void save(int delay) {
			if (!scheduled || delay == 0){
				schedule(delay);
				saveButton.setEnabled(true);
			}
		}
		
	}


	@UiHandler("comment")
	void onTicketCommentChange(ChangeEvent event){
		saveButton.setEnabled(true);
	}
	
	@UiHandler("ticketType")
	void onTicketStatusChange(ChangeEvent event){
		ticketChange.setStatusId(Long.parseLong(status.getValue(status.getSelectedIndex())));
		saveScheduler.save();
	}

	@UiHandler("assignedTo")
	void onAssignedToChange(ChangeEvent event){
		ticketChange.setAssignedToId(Long.parseLong(assignedTo.getValue(assignedTo.getSelectedIndex())));
		saveScheduler.save();
	}
	public TicketDetailPanel(Long ticketId) {
		initWidget(uiBinder.createAndBindUi(this));
		this.ticketId = ticketId;
		initTicketChange();
		ClientUtils.showRemoteCommunicationMessage("loading...");
		UserServiceAsync.INSTANCE.
		fetchTicketDetails(ticketId, new CommonAsyncCallback<TicketDetail>() {

			@Override
			public void onSuccess(TicketDetail result) {
				ClientUtils.hideRemoteCommunicationMessage();
				mapDataToWidgets(result);
			}});
	}
	private void mapDataToWidgets(TicketDetail data){
		title.setText(data.getTitle());
		reportedBy.setText(data.getReportedByFullName());
		reportedDate.setText(data.getCreateDate().toString());
		project.setText(data.getProjectName());
		description.setText(data.getDescription());
		Collection<TicketDetailComment> ticketDetailCommentCollection = data.getComments(); 
		comments.clear();
		if (ticketDetailCommentCollection != null){
			for (TicketDetailComment ticketDetailComment: ticketDetailCommentCollection)
				comments.add(new TicketDetailComments(ticketDetailComment));
		}

		List<TextLongPair> ticketTypeList = data.getProjectTicketTypeList();
		ticketType.clear();
		for (TextLongPair value:ticketTypeList)
			ticketType.addItem(value.getText(), value.getId().toString());
		ClientUtils.selectListBoxItem(ticketType, data.getTicketTypeId());
		
		List<TextLongPair> ticketStatusList = data.getProjectTicketStatusList(); 
		status.clear();
		for (TextLongPair value:ticketStatusList)
			status.addItem(value.getText(), value.getId().toString());
		ClientUtils.selectListBoxItem(status, data.getTicketStatusId());

		List<TextLongPair> projectUserList = data.getProjectUserList(); 
		assignedTo.clear();
		for (TextLongPair value:projectUserList)
			assignedTo.addItem(value.getText(), value.getId().toString());
		ClientUtils.selectListBoxItem(assignedTo, data.getAssigneeId());
	
	}
}
